package com.google.code.jtasks.common.data;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

/**
 * Task data class.
 */
public class Task {
    public final Optional<String> id;
    public final String name;
    public final DateTime startTime;
    public final DateTime endTime;

    @JsonCreator
    public Task(@JsonProperty("id") Optional<String> id,
                @JsonProperty("name") String name,
                @JsonProperty("startTime") DateTime startTime,
                @JsonProperty("endTime") DateTime endTime) {
        this.id = id;
        this.name = name;
        this.startTime = startTime;
        this.endTime = endTime;
    }

    public Task(String name, DateTime startTime, DateTime endTime) {
        this.id = Optional.absent();
        this.name = name;
        this.startTime = startTime;
        this.endTime = endTime;
    }

    /**
     * @return a copy of this task but with identifier set
     * @param id task identifier
     */
    public Task withId(String id) {
        return new Task(Optional.of(id), this.name, this.startTime, this.endTime);
    }

    private static final DateTimeFormatter TO_STRING_FORMAT = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public String toString() {
        return Objects.toStringHelper(this)
            .add("id", id.orNull())
            .add("name", name)
            .add("startTime", TO_STRING_FORMAT.print(startTime))
            .add("endTime", TO_STRING_FORMAT.print(endTime))
            .omitNullValues()
            .toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        Task task = (Task) o;

        return id.equals(task.id) &&
               startTime.equals(task.startTime) && endTime.equals(task.endTime) &&
               name.equals(task.name);
    }

    @Override
    public int hashCode() {
        int result = id.hashCode();
        result = 31 * result + name.hashCode();
        result = 31 * result + startTime.hashCode();
        result = 31 * result + endTime.hashCode();
        return result;
    }
}
